/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Global Trust Authority is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

use thiserror::Error;
use actix_web::{http::StatusCode, HttpResponse, ResponseError};
use serde_json::json;

#[derive(Debug, Error)]
pub enum CertError {
    /// Incorrect input parameter format
    #[error("{0}")]
    IncorrectFormatError(String),

    /// Certificate not found
    #[error("{0}")]
    CertNotFoundError(String),

    /// Certificate already exists
    #[error("{0}")]
    CertExistError(String),

    /// Certificate parsing error
    #[error("{0}")]
    CertParsingError(String),

    /// CRL parsing error
    #[error("{0}")]
    CrlParsingError(String),

    /// Certificate validation error
    #[error("{0}")]
    CertValidationError(String),

    /// Certificate limit reached
    #[error("{0}")]
    CertLimitReached(String),

    /// CRL limit reached
    #[error("{0}")]
    CrlLimitReached(String),

    /// CRL timeout error
    #[error("{0}")]
    CrlTimeoutError(String),

    /// Certificate signature verification failed
    #[error("{0}")]
    CertSignatureVerificationError(String),

    /// Database operation failed
    #[error("Internal Server Error")]
    DatabaseOperationError(String),

    /// Internal error
    #[error("Internal Server Error")]
    InternalError(String),

    /// Too many requests error
    #[error("{0}")]
    TooManyRequestsError(String),

    /// Certificate verification error (legacy compatibility)
    #[error("{0}")]
    VerifyError(String),

    /// Database error (legacy compatibility)
    #[error("Internal Server Error")]
    DbError(String),
}

impl CertError {
    /// Get corresponding HTTP status code
    pub fn status_code(&self) -> StatusCode {
        match self {
            CertError::IncorrectFormatError(_) => StatusCode::BAD_REQUEST,
            CertError::CertNotFoundError(_) => StatusCode::BAD_REQUEST,
            CertError::CertExistError(_) => StatusCode::BAD_REQUEST,
            CertError::CertParsingError(_) => StatusCode::BAD_REQUEST,
            CertError::CrlParsingError(_) => StatusCode::BAD_REQUEST,
            CertError::CertValidationError(_) => StatusCode::BAD_REQUEST,
            CertError::CertLimitReached(_) => StatusCode::BAD_REQUEST,
            CertError::CrlLimitReached(_) => StatusCode::BAD_REQUEST,
            CertError::CrlTimeoutError(_) => StatusCode::BAD_REQUEST,
            CertError::CertSignatureVerificationError(_) => StatusCode::BAD_REQUEST,
            CertError::DatabaseOperationError(_) => StatusCode::INTERNAL_SERVER_ERROR,
            CertError::InternalError(_) => StatusCode::INTERNAL_SERVER_ERROR,
            CertError::TooManyRequestsError(_) => StatusCode::TOO_MANY_REQUESTS,
            CertError::VerifyError(_) => StatusCode::BAD_REQUEST,
            CertError::DbError(_) => StatusCode::INTERNAL_SERVER_ERROR,
        }
    }

    /// Get error message
    pub fn message(&self) -> String {
        self.to_string()
    }
}

/// Implement ResponseError trait for automatic HTTP response conversion
impl ResponseError for CertError {
    fn status_code(&self) -> StatusCode {
        self.status_code()
    }

    fn error_response(&self) -> HttpResponse {
        HttpResponse::build(self.status_code())
            .json(json!({
                "message": self.message()
            }))
    }
}

/// Convert from other error types to CertError
impl From<String> for CertError {
    fn from(err: String) -> Self {
        CertError::InternalError(err)
    }
}

impl From<&str> for CertError {
    fn from(err: &str) -> Self {
        CertError::InternalError(err.to_string())
    }
}

impl From<std::io::Error> for CertError {
    fn from(err: std::io::Error) -> Self {
        CertError::InternalError(err.to_string())
    }
}

impl From<serde_json::Error> for CertError {
    fn from(err: serde_json::Error) -> Self {
        CertError::IncorrectFormatError(err.to_string())
    }
}

// Legacy type alias for backward compatibility
pub type CertVerifyError = CertError;